/****************************************************************************/
/*
* xml parameter direct api.
*/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <errno.h>
#include <signal.h>

#include "cms_common.h"
#include "cms_log.h"
#include "libmdm.h"
#include "cms_mdm.h"
#include "Lzma.h"


/*
	Description: 
		use to get parameter attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		success -- return attribute flags
		fail -- return 0
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXml_GetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint32_t cmsXml_getParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter)
{
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	uint32_t flags = 0;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;

	if((xmlShmCb == NULL) || (parameter == NULL)) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return 0;
	}
	
	XML_LOCK(&xmlShmCb->cmsMutex->lock);

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
		
	while(NTOHS(meta_count)){
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/
			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
			flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			break;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	

	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	return flags;
}

uint32_t cmsXml_getParaValueType(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter)
{
	cmsoffset_t metaOffset, nodeOffset;
	char *metaAddr, *nodeAddr;
	objectNode_t *node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;
	uint32_t type_size = 0;

	if((xmlShmCb == NULL) || (parameter == NULL)) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return 0;
	}
	
	XML_LOCK(&xmlShmCb->cmsMutex->lock);

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
		
	while(NTOHS(meta_count)){
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){/*find meta, change the value*/
			type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
			if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
				type_size = PARAMETER_TYPE_STRING;			
			}
			break;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	
	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	
	return type_size;
}

/*
	Description: 
		use to get parameter attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		success -- return attribute flags
		fail -- return 0
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint32_t cmsXml_getDefaultParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter)
{
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	static uint32_t defaultFlags;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;

	if((xmlShmCb == NULL) || (parameter == NULL)) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return 0;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
		
	while(NTOHS(meta_count)){
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/
			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
			defaultFlags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			if ((defaultFlags & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
				defaultFlags = *((uint32_t *)(object + NTOHDL(attrOffset)+sizeof(uint32_t)));
			}
			else{
				defaultFlags = 0;
			}
			break;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	
	return defaultFlags;
}



/*
	Description: 
		use to get parameter extend attribute
	Parameters:
		xmlShmCb:	xml Shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute extend flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterExtAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint16_t cmsXml_getDefaultParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter)
{
	uint32_t flags;
	static uint16_t attr;

	if(xmlShmCb == NULL || parameter == NULL) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return 0;
	}
	
	flags = cmsXml_getDefaultParameterAttr(xmlShmCb, objOff, parameter);
	attr = flags >> 16;
	
	return attr;
}



/*
	Description: 
		use to get parameter extend attribute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name
	return:
		return attribute extend flags
	example:
	{
		uint32_t *parameter;
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		attr = cmsXmlGetParameterAttr(xmlShmCb, object, (char *)parameter);
	}
*/
uint16_t cmsXml_getParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter)
{
	uint32_t flags;
	static uint16_t attr;

	if(xmlShmCb == NULL || parameter == NULL) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return 0;
	}
	
	flags = cmsXml_getParameterAttr(xmlShmCb, objOff, parameter);
	attr = flags >> 16;
	
	return attr;
}

/*return array of (name, type, value)*/
/*
	Description: 
		use to get default parameter
	Parameters:
		xmlShmCb:	xml Shm control block
		objOff: the object offset
		parameter:	pointer array of p1, p2, p3,....
		count: parameter number
	return:
		return pointer array of (name, value, type_size)
	example:
	{
		parameterValue_t *value;
		char *get[] = {"Name", "Version", "Date", "Description"};
		value = cmsXml_getDefaultParameter(xmlShmCb, object, count, get);
	}
*/
parameterValue_t *cmsXml_getDefaultParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter)
{
	cmsoffset_t metaOffset, nodeOffset, objectOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	parameterValue_t *ptr, *value;
	objectNode_t	*node, *parent, *middle;
	uint16_t meta_count;
	void *meta_ptr, *object, *sobject;
	uint8_t meta_len = 0;
	char **pp;
	uint32_t type = 0;
	uint32_t flags;

	CMS_LOG(LL_FLOOD, "enter\n");
	if(xmlShmCb == NULL || parameter == NULL) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return NULL;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, objOff);

	/*use object to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));
	
	ptr = malloc(sizeof(parameterValue_t)*count);
	value = (parameterValue_t *)ptr;
	memset(value, 0, sizeof(parameterValue_t)*count);
	pp = parameter;
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
		metaOffset = *((cmsoffset_t *)metaAddr);
		
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

		/*use object to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

		meta_count = node->meta_count;

		if(*pp != NULL){
			while(meta_count){

				meta_len = *((uint8_t *)meta_ptr);
				/*compare meta name*/
				if ((meta_len != PADDING_META_LEN)&&!strcmp(*pp, (meta_ptr+sizeof(uint8_t)))){	/*find meta*/		
				
					value->name = *pp; //malloc(name_len);
					value->type_size = *((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)));

					type = value->type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);

					/*-(type_size + attribute offset + meta parameter offset)*/
					objectOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t) + sizeof(cmsoffset_t)*2)));//get parameter value offset
					if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
						/*index child node's default value at i node*/
						parent = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->parent));
						middle = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(parent->child));
						sobject = cmsXmlGetObjRealAddr(xmlShmCb, middle->object);
						value->value = sobject + objectOffset;
					}
					else{
						attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
						flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
						if ((flags & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
							value->value = (object + objectOffset+type);
						}
						else{
							//CMS_LOG(LL_WARNING, "Warning!! Name = %p doesn't have default value.\n", *pp);
						}
					}


					break;
				}
				meta_ptr = meta_ptr + meta_len;
				meta_count--;
				
			}
		}else{
			CMS_LOG(LL_WARNING, "Warning!! Name = %p.\n", *pp);
		}
		if(meta_count == 0){
			free(ptr);
			CMS_LOG(LL_ERROR, "cannot find parameter, %s\n", *pp);
			return NULL;
		}
		count--;
		pp++;	
		value++;
	}
	return ptr;
}


/*
	Description: 
		use to search parameter.
	Parameters:
		xmlShmCb:	xml shm control block
		node: the object node
		parameter:	parameter name
		meta: output parameter of api, the pointer to this object parameter.
	return:
		success -- return cms_ok
		fail -- return cms_nok
*/
int cmsXml_SearchParameter(cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *parameter, char **meta)
{
	uint16_t meta_count;
	char *meta_ptr;
	uint8_t meta_len = 0;
	
	CMS_LOG(LL_FLOOD, "enter \n");
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
	
	while(meta_count){
		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){
			/*find*/
			*meta = meta_ptr;
			CMS_LOG(LL_FLOOD, "leave CMS_OK\n");
			return CMS_OK;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}
	
	CMS_LOG(LL_FLOOD, "leave CMS_NOK\n");
	return CMS_NOK;
}


/*return array of (name, type, value)*/
/*
	Description: 
		use to get parameter
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	pointer array of p1, p2, p3,....
		count: parameter number
	return:
		return pointer array of (name, value, type_size)
	example:
	{
		parameterValue_t *value;
		char *get[] = {"Name", "Version", "Date", "Description"};
		value = cmsXmlGetParameter(xmlShmCb, object, count, get);
	}
*/
parameterValue_t *cmsXml_getParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter)
{
	cmsoffset_t metaOffset, nodeOffset, objectOffset;
	char *metaAddr, *nodeAddr;
	parameterValue_t *ptr, *value;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *object;
	uint8_t meta_len = 0;
	char **pp;
	uint32_t type = 0;

	CMS_LOG(LL_FLOOD, "enter\n");
	
	if((xmlShmCb == NULL) || (parameter == NULL)) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return NULL;
	}

	XML_LOCK(&xmlShmCb->cmsMutex->lock);

	object = cmsXmlGetObjRealAddr(xmlShmCb, objOff);
	ptr = malloc(sizeof(parameterValue_t)*count);
	value = (parameterValue_t *)ptr;
	memset(value, 0, sizeof(parameterValue_t)*count);
	pp = parameter;
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
		metaOffset = *((cmsoffset_t *)metaAddr);
		
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

		/*use object to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

		meta_count = node->meta_count;

		if(*pp != NULL){
			while(meta_count){

				meta_len = *((uint8_t *)meta_ptr);
				/*compare meta name*/
				if ((meta_len != PADDING_META_LEN)&&!strcmp(*pp, (meta_ptr+sizeof(uint8_t)))){	/*find meta*/		
					
					value->name = *pp; //malloc(name_len);
					value->type_size = *((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)));
					if ((value->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
						type = PARAMETER_TYPE_STRING;
					}
					else{
						type = value->type_size;
					}
					switch (type){
					case PARAMETER_TYPE_UINT8:
					case PARAMETER_TYPE_BOOLEAN:
						value->max.unsign.u8 = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u8 = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						break;
					case PARAMETER_TYPE_UINT16:
						value->max.unsign.u16 = *((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u16 = *((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						break;
					case PARAMETER_TYPE_UINT32:
						value->max.unsign.u32 = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u32 = *((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_UINT64:
						value->max.unsign.u64 = *((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.unsign.u64 = *((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					case PARAMETER_TYPE_SINT7:
						value->max.sign.s7 = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s7 = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_SINT15:
						value->max.sign.s15 = *((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s15 = *((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					case PARAMETER_TYPE_SINT31:
						value->max.sign.s31 = *((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s31 = *((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));				
						break;
					case PARAMETER_TYPE_SINT63:
						value->max.sign.s63 = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
						value->min.sign.s63 = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));			
						break;
					}

					objectOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t) + sizeof(cmsoffset_t)*2)));
					value->value = (object + objectOffset);

					break;
				}
				meta_ptr = meta_ptr + meta_len;
				meta_count--;
				
			}
		}else{
			CMS_LOG(LL_WARNING, "Warning!! Name = %p.\n", *pp);
		}
		if(meta_count == 0){
			free(ptr);
			XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
			CMS_LOG(LL_ERROR, "cannot find parameter, %s\n", *pp);
			return NULL;
		}
		count--;
		pp++;	
		value++;
	}
	
	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	return ptr;
}


/*
	Description: 
		use to get one parameter's value.
	Parameters:
		xmlShmCb:	xml shm control block
		OID: object id
		IA: object instance array
		parameter:	parameter name
		value: output parameter of api, the pointer to this object parameter value.
	return:
		success -- return cms_ok
		fail -- return cms_nok
*/
int cmsXml_getParameterByOID(cmsXmlCb_t *xmlShmCb, uint32_t OID, uint64_t IA, char *parameter, void *value)
{
	parameterValue_t *paraValue = NULL;
	void *object = NULL;
	uint32_t objOff;
	uintptr_t *objPara;
	char **temp;

	if((xmlShmCb == NULL) || (parameter == NULL))
		return CMS_NOK;
	
	objPara = malloc(sizeof(void*)*1);
	temp = (char **)objPara;
	*objPara = (uintptr_t)parameter;
	
	object = cmsXml_GetObjectByOID(xmlShmCb, OID, IA, NULL_IF_NOT_EXISTED);
	if(object){
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
		paraValue = cmsXml_getParameter(xmlShmCb, objOff, 1, temp);
		if(paraValue == NULL){
			free(temp);
			return CMS_NOK;
		}

		if((paraValue->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
			memcpy(value, paraValue->value, strlen(paraValue->value)+1);
		}else{
			memcpy(value, paraValue->value, (paraValue->type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS)));
		}
		
		free(temp);
		cmsXml_freeParameterBuffer(paraValue, 1);
	}else{
		free(temp);
		return CMS_NOK;
	}


	return CMS_OK;
}


/*
	Description: 
		use to get one parameter's value.
	Parameters:
		xmlShmCb:	xml shm control block
		objPath:  object full path name
		parameter:	parameter name
		value: output parameter of api, the pointer to this object parameter value.
	return:
		success -- return cms_ok
		fail -- return cms_nok
*/	
int cmsXml_getParameterByObjPath(cmsXmlCb_t *xmlShmCb, char *objPath, char *parameter, void *value)
{
	parameterValue_t *paraValue = NULL;
	void *object = NULL;
	uint32_t objOff;
	uintptr_t *objPara;
	char **temp;

	if((xmlShmCb == NULL) || (parameter == NULL))
		return CMS_NOK;
	
	objPara = malloc(sizeof(void*)*1);
	temp = (char **)objPara;
	*objPara = (uintptr_t)parameter;
	
	object = cmsXml_GetObjectByName(xmlShmCb, objPath, NULL_IF_NOT_EXISTED);
	if(object){
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
		paraValue = cmsXml_getParameter(xmlShmCb, objOff, 1, temp);
		if(paraValue == NULL){
			free(temp);
			return CMS_NOK;
		}
		if((paraValue->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
			memcpy(value, paraValue->value, strlen(paraValue->value)+1);
		}else{
			memcpy(value, paraValue->value, (paraValue->type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS)));
		}
		
		free(temp);
		cmsXml_freeParameterBuffer(paraValue, 1);
	}else{
		free(temp);
		return CMS_NOK;
	}

	return CMS_OK;
}

static uint64_t cms64EndianTransfer(uint64_t value){
#ifdef BIGENDIAN
	uint32_t *endianPtr;
	uint32_t endian1 = 0;
	uint32_t endian2 = 0;
	uint64_t endian = 0;

	endianPtr = (uint32_t *)&value;
	memcpy(&endian1, endianPtr, sizeof(uint32_t));
	memcpy(&endian2, endianPtr + 1, sizeof(uint32_t));
	endian1 = NTOHL(endian1);
	endian2 = NTOHL(endian2);
	endianPtr = (uint32_t *)&endian;
	memcpy(endianPtr+1, &endian1, sizeof(uint32_t));
	memcpy(endianPtr, &endian2, sizeof(uint32_t));

	return endian;
#else
	return value;
#endif
}

/*______________________________________________________________________________
**	htoi
**
**	descriptions:
**	Convert hex-ascii to integer
**	parameters:
**	local:
**	global:
**	return:
**	called by:
**	call:
**	revision:
**____________________________________________________________________________*/
static int
htoi(
	char	*s
)
{
	int i = 0;
	char	c;

	while((c = *s++) != '\0'){
		if(c == 'x')
			continue;		/* allow 0x notation */
		if('0' <= c && c <= '9')
			i = (i * 16) + (c - '0');
		else if('a' <= c && c <= 'f')
			i = (i * 16) + (c - 'a' + 10);
		else if('A' <= c && c <= 'F')
			i = (i * 16) + (c - 'A' + 10);
		else
			goto error_ret;
			//break;
	}
	return i;
error_ret:
	return -1;
} /* htoi */

/*
	descriptions:
		Convert an Ethernet address from Hex/ASCII to binary
	parameters:
	
	return:
	
*/
static int
gether(
	uint8_t	*out,
	char	*cp
)
{
	int i,ret = 0;
	char	*pcp;

	pcp = cp;
	for(i=6; i!=0; i--)
	{
		if(i>1 && (cp = strchr(pcp,':')) == NULL)
			break;
		*cp = 0;
		ret = htoi(pcp);
		if(ret<0)
			goto error_ret;
		else
			*out++ = ret;
		pcp = cp+1;
	}
	//*out++ = htoi(pcp);
	//i--;
	return i;
error_ret:
	return -1;
}

/*used to trans parameter value from string to uing32, atoi return int, if set 4294967295, only get half.*/
uint32_t cms_atoi(const char *str)
{
	uint32_t integer = 0;

	if(str == NULL)
		return 0;
	
	while(*str >= '0' && *str <= '9'){

		integer = integer*10 + *str - '0';
		str++;
	}

	return integer;
}


/*set parameter needs to mark the node has been configed!*/
/*
	Description: 
		use to set parameter
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		count:	parameter number
		parameter:	pointer array of p1, v1, t1, p2, v2, t2, p3, v3, t3....
					p: parameter name pointer
					v: parameter value pointer
					t: parameter type pointer, you can use string(PARAMETER_TYPE_STRING) 
						or native type(ex. PARAMETER_TYPE_UINT8)
	return:
		return CMS_OK
	call by:
		1. cms_db, direct access for change parameter value 
		2. Front-end, indirect access for change parameter value
		3. xtos, direct access for xml Shm initial value
	example:
		uint32_t *type_char = PARAMETER_TYPE_STRING;
		char *set[] = {"Date", "Change", (char *)&type_char};	//p1, v1, t1
		int count = 1;
		cmsXmlSetParameter(xmlShmCb, object, count, set);

*/
int cmsXml_setParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter)
{
	cmsoffset_t metaOffset, nodeOffset, paraOffset, attrOffset;
	char *metaAddr, *nodeAddr, *meta_ptr;
	int i=0;
	objectNode_t *node, *parent, *middle;
	uint32_t size = 0, type_size = 0, real_size = 0;
	uint8_t meta_len = 0;
	uint16_t meta_count, flag=0, restore = 0;
	uint32_t type = 0;
	void *object, *sobject;
	uint32_t attr = 0;
	uint64_t tempValue;
	uint64_t maxValue;
	uint64_t minValue;
	char	*pcp = NULL;
	char *tmpStr;
	uint8_t outStr[6], *macPtr, oldMacPtr[6] = {0};
	int errorFlag = 0;
	//char *nodeName;
	int ret = 0, isString = 0, result = CMS_OK;
#if !defined(SYSDEF_PARSER_ON_HOST)
	char *stringAddr = NULL;
	uint32_t *stringTmp = NULL;
	char **stringDouble;
#endif

	CMS_LOG(LL_FLOOD, "enter aaa\n");
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}
	
	XML_LOCK(&xmlShmCb->cmsMutex->lock);
	if(parameter == NULL) {
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	while(count > 0){
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
		metaOffset = *((cmsoffset_t *)metaAddr);

		/*use oid to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

		meta_count = NTOHS(node->meta_count);
		CMS_LOG(LL_FLOOD, "meta count is %d, current paramter %s\n", meta_count, *(parameter+i));
			
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		if((*(parameter+i)) != NULL && (*(parameter+i+1)) != NULL && (*(parameter+i+2))!= NULL){
			if (cmsXml_SearchParameter(xmlShmCb, node, *(parameter+i), &meta_ptr) == CMS_OK){


				meta_len = *((uint8_t *)meta_ptr);
				
				type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
				paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
				attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
				type = *((uint32_t *)(*(parameter+i+2)));
				
				/*get parameter attribute*/
				attr = NTOHL(*((uint32_t *)(object+attrOffset)));
#ifndef SYSDEF_PARSER_ON_HOST					
				if ((attr & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY){
					/*if the parameter is not writeable, return i?*/
					CMS_LOG(LL_ERROR, "config.xml error.\n\r");
					goto next_parameter;
				}
#endif					
				/*find offset and type of the parameter, use type to convert the parameter from string to value*/
				if(*(parameter+i+1)!=NULL)
				{
					isString = 0;
					if ((type & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
						/*merge this part with cmsXmlConvertToValue()??!!*/
						size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
						if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
							type_size = PARAMETER_TYPE_STRING;			
						}
	
						isString = 1;
					}
					else if ((type & PARAMETER_RESTORE) == PARAMETER_RESTORE){ /*check is this a restore action?*/
						restore = 1;	/*mark there is a restore action and need to check NODE's ATTR_NODECONFIGURED*/ 					
						/*index child?*/
						if (node->attributes & ATTR_INDEXCHILD){
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							parent = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->parent));
							middle = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(parent->child));
							sobject = cmsXmlGetObjRealAddr(xmlShmCb, middle->object);
							/*tmp use read only, maybe we need to add one attribute to present this parameter cannot be restored*/
							
							/*restore value*/
							memcpy((object+paraOffset), (sobject+paraOffset), size);
							/*resotre attr here*/
							memcpy((object+attrOffset), (sobject+attrOffset), sizeof(uint32_t));
							goto next_parameter;
						}
						/*check default parameter exist?*/
						if ((attr & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
							/*_default exist*/
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							/*restore value*/
							memcpy((object+paraOffset), (object+paraOffset+size), size);							
						}
						else{
							/*_default non-exist*/
							size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
							memset((object+paraOffset), 0, size);
						}
						/*check default attribute exist?*/
						if ((attr & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
							/*default attribute exist*/
							size = sizeof(uint32_t);
							/*restore value*/
							memcpy((object+attrOffset), (object+attrOffset+size), size);							
						}
						else{
							/*default attribute non-exist*/
							size = sizeof(uint32_t);
							/*remove attibute except fix bit*/
							attr &= PARAMETER_ATTR_FIX_BITS;
							memcpy((object+attrOffset), &attr, size);
						}
							
						goto next_parameter;	/*next parameter*/
							
					}
					else{
						/*the input parameter's type is not string, type: input type, type_size: original type*/
						if (type != type_size){
							XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
							CMS_LOG(LL_ERROR, "Set error, Pid:%d objectId:%d Name:(%s), type passIn:0x%x expect:0x%x\n", getpid(), xmlShmCb->OID,*(parameter+i), type, type_size);
							return CMS_NOK;
						}
					}			
					
					/*copy the value*/
					maxValue = minValue = tempValue = 0;
					switch(type_size){
						case PARAMETER_TYPE_UINT8:
						case PARAMETER_TYPE_BOOLEAN:
							/*convert to value here*/
							maxValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							minValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint8_t *)(*(parameter+i+1));
							}
							if((uint8_t)tempValue > (uint8_t)maxValue || (uint8_t)tempValue < (uint8_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint8 The value of parameter \"%s\" is out of range(%u-%u). Value=%u",
									*(parameter+i), (uint8_t)minValue, (uint8_t)maxValue, (uint8_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((uint8_t *)(object+paraOffset)) == (uint8_t)tempValue){
								result = CMS_NOCHANGE;
							}
							*((uint8_t *)(object+paraOffset)) = (uint8_t)tempValue;
//							memcpy((object+paraOffset), ptr, size);
							break;
						case PARAMETER_TYPE_UINT16:
							/*convert to value here*/
							maxValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint16_t *)(*(parameter+i+1));
							}								
							if((uint16_t)tempValue > (uint16_t)maxValue || (uint16_t)tempValue < (uint16_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint16 The value of parameter \"%s\" is out of range(%u-%u). Value=%u\n\r",
									*(parameter+i), (uint16_t)minValue, (uint16_t)maxValue, (uint16_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((uint16_t *)(object+paraOffset)) == HTONS((uint16_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((uint16_t *)(object+paraOffset)) = HTONS((uint16_t)tempValue);
//							memcpy((object+paraOffset), &unsign16, size);
							break;
						case PARAMETER_TYPE_UINT32:
							/*convert to value here*/
							maxValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint32_t *)(*(parameter+i+1));
							}								
							if((uint32_t)tempValue > (uint32_t)maxValue || (uint32_t)tempValue < (uint32_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint32 The value of parameter \"%s\" is out of range(%u-%u). Error value=%u\n\r",
									*(parameter+i), (uint32_t)minValue, (uint32_t)maxValue, (uint32_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((uint32_t *)(object+paraOffset)) == HTONL((uint32_t)tempValue)){
								result = CMS_NOCHANGE;
							}								
							*((uint32_t *)(object+paraOffset)) = HTONL((uint32_t)tempValue);
//							memcpy((object+paraOffset), &unsign32, size);
							break;
						case PARAMETER_TYPE_MAC:
							/*convert to value here*/
							if (isString){
								tmpStr= *(parameter+i+1);
								{
									int len = 0;
									len=strlen(tmpStr);
									if(len!=17)
									{
										CMS_LOG(LL_ERROR, "mac1 The value of parameter \"%s\" is out of range. Error value=%s, MAC value type must like XX:XX:XX:XX:XX:XX\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}
									pcp = *(parameter+i+1);
									ret = gether(outStr, pcp);
									if(ret > 0)
									{
										CMS_LOG(LL_ERROR, "mac2 The value of parameter \"%s\" is out of range. Error value=%s, MAC value type must like XX:XX:XX:XX:XX:XX\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}
									else if(ret == -1)
									{
										CMS_LOG(LL_ERROR, "mac3 The value of parameter \"%s\" is out of range. Error value=%s, MAC address must between 0~9,a~f or A~F.\n\r",*(parameter+i), tmpStr);
										errorFlag = 1;
										break;
									}	
								}	
								macPtr = (uint8_t *)&outStr;
							}
							else{
								macPtr = (uint8_t *)(*(parameter+i+1));
							}
							
							memcpy(oldMacPtr, object+paraOffset, 6);
							
			
							if((macPtr[0] == oldMacPtr[0]) && (macPtr[1] == oldMacPtr[1]) && (macPtr[2] == oldMacPtr[2]) &&
								(macPtr[3] == oldMacPtr[3]) && (macPtr[4] == oldMacPtr[4]) && (macPtr[5] == oldMacPtr[5])){
								CMS_LOG(LL_WARNING, "[%s-%d], no change, old mac %02x:%02x:%02x:%02x:%02x:%02x, newMac %02x:%02x:%02x:%02x:%02x:%02x\n", 
									__FUNCTION__, __LINE__,
									(unsigned char)oldMacPtr[0], 
									(unsigned char)oldMacPtr[1],
									(unsigned char)oldMacPtr[2],
									(unsigned char)oldMacPtr[3],
									(unsigned char)oldMacPtr[4],
									(unsigned char)oldMacPtr[5],
									(unsigned char)macPtr[0], 
									(unsigned char)macPtr[1],
									(unsigned char)macPtr[2],
									(unsigned char)macPtr[3],
									(unsigned char)macPtr[4],
									(unsigned char)macPtr[5]);
								result = CMS_NOCHANGE;
							}
			
							memcpy((object+paraOffset), macPtr, 6);
							break;
						case PARAMETER_TYPE_UINT64:
							maxValue = cms64EndianTransfer(*((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = cms64EndianTransfer(*((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoull(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoull(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(uint64_t *)(*(parameter+i+1));
							}									
							if((uint64_t)tempValue > (uint64_t)maxValue || (uint64_t)tempValue < (uint64_t)minValue)
							{
								CMS_LOG(LL_ERROR, "uint64 The value of parameter \"%s\" is out of range("U64_"-"U64_"). Error value="U64_"\n\r",
									*(parameter+i), (uint64_t)minValue, (uint64_t)maxValue, (uint64_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((uint64_t *)(object+paraOffset)) == cms64EndianTransfer((uint64_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((uint64_t *)(object+paraOffset)) = cms64EndianTransfer((uint64_t)tempValue);
							break;
						case PARAMETER_TYPE_SINT7:
							/*convert to value here*/
							maxValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							minValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int8_t *)(*(parameter+i+1));
							}									
							if((int8_t)tempValue > (int8_t)maxValue || (int8_t)tempValue < (int8_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint7 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int8_t)minValue, (int8_t)maxValue, (int8_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((int8_t *)(object+paraOffset)) == (int8_t)tempValue){
								result = CMS_NOCHANGE;
							}
							*((int8_t *)(object+paraOffset)) = (int8_t)tempValue;
//							memcpy((object+paraOffset), ptr, size);
							break;
						case PARAMETER_TYPE_SINT15:
							/*convert to value here*/
							maxValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int16_t *)(*(parameter+i+1));
							}									
							if((int16_t)tempValue > (int16_t)maxValue || (int16_t)tempValue < (int16_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint15 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int16_t)minValue, (int16_t)maxValue, (int16_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((int16_t *)(object+paraOffset)) == HTONS((int16_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int16_t *)(object+paraOffset)) = HTONS((int16_t)tempValue);
//							memcpy((object+paraOffset), &unsign16, size);
							break;
						case PARAMETER_TYPE_SINT31:
							/*convert to value here*/
							maxValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int32_t *)(*(parameter+i+1));
							}									
							if((int32_t)tempValue > (int32_t)maxValue || (int32_t)tempValue < (int32_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint31 The value of parameter \"%s\" is out of range(%d-%d). Error value=%d\n\r",
									*(parameter+i), (int32_t)minValue, (int32_t)maxValue, (int32_t)tempValue);
								errorFlag = 1;
								break;
							}
							if(*((int32_t *)(object+paraOffset)) == HTONL((int32_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int32_t *)(object+paraOffset)) = HTONL((int32_t)tempValue);
//							memcpy((object+paraOffset), &unsign32, size);
							break;
						case PARAMETER_TYPE_SINT63:
							maxValue = cms64EndianTransfer(*((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							minValue = cms64EndianTransfer(*((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
							if (isString){
								if(strncmp(*(parameter+i+1), "0X", 2) == 0 ||
									strncmp(*(parameter+i+1), "0x", 2) == 0){
									tempValue = strtoll(*(parameter+i+1), NULL, 16);
								}else{
									tempValue = strtoll(*(parameter+i+1), NULL, 10);
								}
							}
							else{
								tempValue = *(int64_t *)(*(parameter+i+1));
							}									
							if((int64_t)tempValue > (int64_t)maxValue || (int64_t)tempValue < (int64_t)minValue)
							{
								CMS_LOG(LL_ERROR, "sint63 The value of parameter \"%s\" is out of range("S64_"-"S64_"). Error value="S64_"\n\r",
									*(parameter+i), (int64_t)minValue, (int64_t)maxValue, (int64_t)tempValue);
									errorFlag = 1;
								break;
							}
							if(*((int64_t *)(object+paraOffset)) == cms64EndianTransfer((int64_t)tempValue)){
								result = CMS_NOCHANGE;
							}
							*((int64_t *)(object+paraOffset)) = cms64EndianTransfer((int64_t)tempValue);
							break;
						case PARAMETER_TYPE_DATETIME:
							if(strlen(*(parameter+i+1)) > PARAMETER_TYPE_DATETIME)
							{
								CMS_LOG(LL_ERROR, "The value of parameter \"%s\" is too long. Error value=%s\n\r",*(parameter+i), *(parameter+i+1));
									errorFlag = 1;
								break;
							}
							if(strcmp((object+paraOffset), *(parameter+i+1)) == 0){
								result = CMS_NOCHANGE;
							}								
							memcpy((object+paraOffset), *(parameter+i+1), PARAMETER_TYPE_DATETIME);
							break;
						case PARAMETER_TYPE_STRING:
							real_size = strlen(*(parameter+i+1));
#if !defined(SYSDEF_PARSER_ON_HOST)
							if ( attr & PARAMETER_ATTR_NO_MALLOC )
							{
								
								stringTmp = ( object + paraOffset );
								stringDouble = (char **)stringTmp;
								if ( *stringDouble != NULL ) /* already malloc space. */
								{
									if ( strlen( *stringDouble ) > real_size ) /* new string length is smaller than old string. */
									{
										strncpy( *stringDouble, *( parameter + i + 1 ), real_size );
										*( (char *)( *stringDouble + real_size ) ) = '\0';
									}
									else if ( strncmp( *stringDouble, *( parameter + i + 1 ), real_size ) == 0 )
									{
										result = CMS_NOCHANGE;
									}
									else /* malloc new space. */
									{
										cmsXml_SetStringShmOffset( xmlShmCb, real_size + 1 );
										stringAddr = ( xmlShmCb->baseaddr + cmsXmlGetStringShmOffset( xmlShmCb ) );
										strncpy( stringAddr, *( parameter + i + 1 ), real_size );
										*( (char *)( stringAddr + real_size ) ) = '\0';
										/* write realAddr to paraOffset. */
										*stringTmp = *(uint32_t *)stringAddr;
									}
								}
								else /* malloc new space. */
								{
									cmsXml_SetStringShmOffset( xmlShmCb, real_size + 1 );
									stringAddr = ( xmlShmCb->baseaddr + cmsXmlGetStringShmOffset( xmlShmCb ) );
									strncpy( stringAddr, *( parameter + i + 1 ), real_size );
									*( (char *)( stringAddr + real_size ) ) = '\0';
									/* write realAddr to paraOffset. */
									*stringTmp = *(uint32_t *)stringAddr;
								}
							}
							else
#endif
							{
								if ( real_size > ( size - 1 ) ) /*size - 1 is for '\0'*/
								{
									CMS_LOG( LL_ERROR, "The value of parameter \"%s\" is too long. Error value=%s\n\r", *( parameter + i ), *( parameter + i + 1 ) );
									errorFlag = 1;
									break;
								}
								if ( strcmp( ( object + paraOffset ), *( parameter + i + 1 ) ) == 0 )
								{
									result = CMS_NOCHANGE;
								}

								/*merge bug fix from Andrew at 12/26*/
								memcpy( ( object + paraOffset ), *( parameter + i + 1 ), real_size );
								*( (char *)( object + paraOffset + real_size ) ) = '\0';
							}
							break;
						default:
							CMS_LOG(LL_ERROR, "Set Parameter type error!!\n");
							break;
					}
					if(errorFlag == 1){
						result = CMS_OUTOFRANGE;
						XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
						CMS_LOG(LL_ERROR, "Set Parameter error when value is not in the range or parameter. return ok and store the default value.\n");
						return result;
					}
				}
				/*flag is used to mark this node is configured*/
				/*SYSDEF_PARSER_ON_HOST: if NO, means this is librdm.so*/
#ifndef SYSDEF_PARSER_ON_HOST	/*x2s default value should not mark this node to be configured!*/		
				if (attr & PARAMETER_ATTR_CONFIG){
					flag = 1;	/*this node has been configured and also need to save to config.xml*/
				}
#endif
			}
		}else{
			CMS_LOG(LL_WARNING, "Warning!! Name = %p, Value = %p, Type = %p.\n", (*(parameter+i)), (*(parameter+i+1)), (*(parameter+i+2)));
		}
next_parameter: 	
		count--;
		i += 3;
	}

	if ((flag == 1)||(restore == 1)){
		if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
			ret = 1;
			/*if the node is index child, don't use cmsXml_CheckObjectChg() to check object change or not*/
			/*index child cannot use cmsXml_CheckObjectChg() to remove ATTR_NODECONFIGURED, index child needs to use cmsXml_SetIndexObject()*/
			/*because index child's ATTR_NODECONFIGURED not only for saving config.xml but also for checking child node occupied or not*/
		}
		else{
			xmlShmCb->offset = NTOHL( objOff );
			ret = cmsXml_checkObjectChg(xmlShmCb, node);
		}

		if (result != CMS_NOCHANGE){
			if(ret){
				cmsXml_setNodeStatus(xmlShmCb, node, ret);
			}
		}
	}

	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	return result;
}

/*
	Description: 
		use to set parameter from parameter list.
	Parameters:
		xmlShmCb:	xml shm control block
		objoff: the object offset
		parameterList:	parameter list, include name, value, type
	return:
		success -- return CMS_OK
		fail -- return CMS_NOK
*/
int cmsXml_setParameterByParaList(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, paraValueSettingList_t *parameterList)
{
	paraValueSettingList_t *curPara = NULL;
	setParaValue_t param;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = FALSE;
	uint32_t objID = 0; 
	uint64_t objIA = 0;
	char objInfo[EVENT_CONTENT_MAX] = {0};
	int sendFlag = 0;
	int ret = CMS_NOK;
#endif

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}

#ifdef DBUS_OBJECT_NOTIFY
	objID = cmsXml_GetOIDByOffset(xmlShmCb, objOff);
	objIA = cmsXmlGetPreObjIA(xmlShmCb, objOff);

	if(objID == -1)
		return CMS_NOK;

	isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objID);
#endif

	curPara = parameterList;
	while(curPara && (strlen(curPara->parameter) != 0)){	
		memset(&param,0,sizeof(param));
		param.parameter=curPara->parameter;
		param.type=&(curPara->type);
		param.value=curPara->value;
#ifdef DBUS_OBJECT_NOTIFY
		ret = cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)&param);
		if((isNeedNotfiy == TRUE) && (ret == CMS_OK)){
			if(sendFlag == 0){
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d", objID, objIA, CMS_OBJ_SET);
				sendFlag = 1;
			}
			
			if((strlen(objInfo) + strlen(curPara->parameter)) >= EVENT_CONTENT_MAX){
				cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d;%s", objID, objIA, CMS_OBJ_SET, curPara->parameter);
			}else
				sprintf(objInfo+strlen(objInfo), ";%s", curPara->parameter);
		}
#else
		cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)&param);
#endif

		curPara = curPara->next;
	#ifdef DBUS_OBJECT_NOTIFY
		if((isNeedNotfiy == TRUE) && (curPara == NULL) && (sendFlag == 1)){
			cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
		}
	#endif
	}
	
	return CMS_OK;
}

/*
	Description: 
		use to set one parameter.
	Parameters:
		xmlShmCb:	xml shm control block
		OID: object id
		IA: object instance array
		parameter: name
		type: parameter value type
		value: parameter value
	return:
		success -- return CMS_OK
		fail -- return CMS_NOK
*/
int cmsXml_setOneParameterByOID(cmsXmlCb_t *xmlShmCb, uint32_t OID, uint64_t IA, char *parameter, uint32_t type, void *value)
{
	void *object = NULL;
	uint32_t objOff = 0;
	setParaValue_t *setPtr, *tmpPtr;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, OID);
	char objInfo[EVENT_CONTENT_MAX] = {0};
	int ret = CMS_NOK;
#endif
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}

	if((parameter == NULL) || (value == NULL))
		return CMS_NOK;

	
	object = cmsXml_GetObjectByOID(xmlShmCb, OID, IA, NULL_IF_NOT_EXISTED);
	if(object){

		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);

		tmpPtr = setPtr = malloc(sizeof(setParaValue_t)*1);

		setPtr->parameter = parameter;
		setPtr->value = value;
		setPtr->type = &type;

#ifdef DBUS_OBJECT_NOTIFY
		ret = cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)tmpPtr);
		if((isNeedNotfiy == TRUE) && (ret == CMS_OK)){
			sprintf(objInfo, "%u;%ju;%d;%s", OID, IA, CMS_OBJ_SET,parameter);
			cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
		}
#else
		cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)tmpPtr);
#endif
		free(tmpPtr);
	}else{
		return CMS_NOK;
	}

	return CMS_OK;
}


/*
	Description: 
		use to set one parameter.
	Parameters:
		xmlShmCb: xml shm control block
		objPath: object full path name
		parameter: name
		type: parameter value type
		value: parameter value
	return:
		success -- return CMS_OK
		fail -- return CMS_NOK
*/
int cmsXml_setOneParameterByPath(cmsXmlCb_t *xmlShmCb, char *objPath, char *parameter, uint32_t type, void *value)
{
	void *object = NULL;
	uint32_t objOff = 0;
	setParaValue_t *setPtr, *tmpPtr;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = FALSE;
	char objInfo[EVENT_CONTENT_MAX] = {0};
	uint32_t objID = 0;
	uint64_t objIA = 0;
	int ret = CMS_NOK;
#endif
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}
	
	if((parameter == NULL) || (value == NULL))
		return CMS_NOK;
	
#ifdef DBUS_OBJECT_NOTIFY
	objectList_t *objList = cmsXml_GetObjListByName(xmlShmCb, objPath);
	if (objList != NULL){
		objID = objList->OID;
		objIA = objList->IA;
	}else{
		return CMS_NOK;
	}

	isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objID);
#endif
	
	object = cmsXml_GetObjectByName(xmlShmCb, objPath, NULL_IF_NOT_EXISTED);
	if(object){

		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);

		tmpPtr = setPtr = malloc(sizeof(setParaValue_t)*1);

		setPtr->parameter = parameter;
		setPtr->value = value;
		setPtr->type = &type;
#ifdef DBUS_OBJECT_NOTIFY
		ret = cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)tmpPtr);
		if((isNeedNotfiy == TRUE) && (ret == CMS_OK)){
			sprintf(objInfo, "%u;%ju;%d;%s", objID, objIA, CMS_OBJ_SET,parameter);
			cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
		}
#else
		cmsXml_setParameter(xmlShmCb, objOff, 1, (char **)tmpPtr);
#endif
		free(tmpPtr);
	}else{
		return CMS_NOK;
	}

	return CMS_OK;
}


/*
	Description: 
		use to set parameter attibute
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		parameter:	parameter name		
		flags:	attribute type
		active: active type
		#define PARAMETER_ATTR_ACTIVE	1
		#define PARAMETER_ATTR_INACTIVE	0
		any possibility that we configure attribute but no parameter?!
	return:
		return CMS_OK
	example:
	{
		*p2 = "Version"
		parameter = (uint32_t *)p2;
		flags |= PARAMETER_ATTR_WRITEABLE;
		cmsXmlSetParameterAttr(xmlShmCb, object, (char *)parameter, flags, PARAMETER_ATTR_ACTIVE);
	}
*/
int cmsXml_setParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter, uint32_t flags, int active)
{
	cmsoffset_t metaOffset, nodeOffset, attrOffset;
	char *metaAddr, *nodeAddr;
	uint32_t attr = 0;
	uint8_t meta_len = 0;
	uint16_t meta_count;
	void *meta_ptr, *object;
	objectNode_t *node;
#ifndef SYSDEF_PARSER_ON_HOST	
	int ret = 0;
#endif
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}
	
	XML_LOCK(&xmlShmCb->cmsMutex->lock);
	if(parameter == NULL) {
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return CMS_NOK;
	}

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)(metaAddr));

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)(nodeAddr));
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	meta_count = node->meta_count;
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));	
	while(meta_count){


		meta_len = *((uint8_t *)meta_ptr);
		/*compare meta name*/
		if ((meta_len != PADDING_META_LEN)&&!strcmp(parameter, (meta_ptr+sizeof(uint8_t)))){	/*find meta, change the value*/

			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t)))));
			attr = NTOHL(*((uint32_t *)(object + attrOffset)));
			if (active == PARAMETER_ATTR_ACTIVE){
#ifndef SYSDEF_PARSER_ON_HOST
				attr |= (flags & ~PARAMETER_ATTR_FIX_BITS);	/*PARAMETER_ATTR_CONFIG cannot modify*/
#else
				attr |= flags;
#endif
			}
			else{
#ifndef SYSDEF_PARSER_ON_HOST				
				attr &= ~(flags & ~PARAMETER_ATTR_FIX_BITS);
#else
				attr &= ~flags;
#endif
			}
			if (attr & PARAMETER_ATTR_CONFIG){
#ifndef SYSDEF_PARSER_ON_HOST	/*xtos default value should not mark this node to be configured!*/	
				if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
					ret = 1;
					/*if the node is index child, don't use cmsXml_CheckObjectChg() to check object change or not*/
					/*index child cannot use cmsXml_CheckObjectChg() to remove ATTR_NODECONFIGURED, index child needs to use cmsXml_SetIndexObject()*/
					/*because index child's ATTR_NODECONFIGURED not only for saving config.xml but also for checking child node occupied or not*/
				}
				else{
					xmlShmCb->offset = objOff;
					ret = cmsXml_checkObjectChg(xmlShmCb, node);
				}
				if(ret){
					cmsXml_setNodeStatus(xmlShmCb, node, ret);
				}
#endif				
			}
			*((uint32_t *)(object + attrOffset)) = HTONL(attr);
//			memcpy((object + attrOffset), &attr, sizeof(uint32_t));
			XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
			return CMS_OK;
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}	

	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	return CMS_NOK;
}


/*
	Description: 
		use to set one parameter ext attr.
	Parameters:
		xmlShmCb: xml shm control block
		objOff: object offset
		parameter: name
		flags: ext attr
		active: 
	return:
		success -- return CMS_OK
		fail -- return CMS_NOK
*/
int cmsXml_setParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter, uint16_t flags, int active)
{
	uint32_t attr;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}
	
	if(parameter == NULL) {
		CMS_LOG(LL_ERROR, "Error!! parameter is nil\n");
		return CMS_NOK;
	}

	attr = flags << 16;

	cmsXml_setParameterAttr(xmlShmCb, objOff, parameter, attr, active);
	
	return CMS_OK;
}

/*
	Description: 
		get object ptr by name.
	Parameters:
		xmlShmCb: xml shm control block;
		pathName: object full path name;
	return:
		success -- return object ptr.
		fail -- return NULL.
*/
void *cmsXml_getObjectByPathName( cmsXmlCb_t *xmlShmCb, char *pathName)
{
	void *object = NULL;

	object = cmsXml_GetObjectByName(xmlShmCb, pathName, NULL_IF_NOT_EXISTED);

	return object;
}

/*
	Description: 
		get object ptr by OID.
	Parameters:
		xmlShmCb: xml shm control block;
		objId: object ID, please refer to cmsXml_obj_id.h.
		objIA: instance array.
	return:
		success -- return object ptr.
		fail -- return NULL.
*/
void *cmsXml_getObjectByOID( cmsXmlCb_t *xmlShmCb, uint32_t objId, uint64_t objIA)
{
	void *object = NULL;

	object = cmsXml_GetObjectByOID(xmlShmCb, objId, objIA, NULL_IF_NOT_EXISTED);

	return object;
}


/*
	Description: 
		use to get parameter name
	Parameters:
		xmlShmCb:	xml shm control block
		node: the node pointer
		index: parameter index number
	return:
		return pointer of name
		
*/
char *cmsXml_getParameterNamePtr(cmsXmlCb_t *xmlShmCb, objectNode_t *node, int index)
{
	void *meta_ptr;
	char *ptr = NULL;
	uint8_t meta_len = 0;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}

	if (index > node->meta_count)
		return NULL;

	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, node->meta);	

	while(index > 0){
		/*get meta ptr*/

		meta_len = *((uint8_t *)meta_ptr);

		ptr = meta_ptr + sizeof(uint8_t);

		meta_ptr = meta_ptr + meta_len;

		index--;
	}
	if (meta_len == PADDING_META_LEN){
		return NULL;	/*it's padding meta*/
	}

	return ptr;
}

/*
	Description: 
		use to get the node's all parameter names
	Parameters:
		xmlShmCb:	xml shm control block
		id: the object node's offset id
	return:
		return a double pointer point to the parameter pointer array
		p1, p2, p3, p4.....
	note:
		after using, you MUST call cmsXml_freeParameterNameBuffer() 
		to free the memory of parameter name pointer
*/
void **cmsXml_getParameterNameByID(cmsXmlCb_t *xmlShmCb, cmsoffset_t id)
{
	void **name, *object, *value;
	int i = 0;
	uint16_t count = 0;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	
	object = cmsXml_getObjectByID(xmlShmCb, id);
	if(object == NULL)
		return NULL;

	if ((xmlShmCb->objectNode->attributes & ATTR_OBJECTNODE) != ATTR_OBJECTNODE){
		CMS_LOG(LL_ERROR, "The id is not a object node\r\n");
		return NULL;
	}
	name = malloc(sizeof(void *)*xmlShmCb->objectNode->meta_count);
	memset(name, 0, sizeof(void *)*xmlShmCb->objectNode->meta_count);
	value = name;
	for (i = 1; i < (xmlShmCb->objectNode->meta_count + 1); i++){
		*name = cmsXml_getParameterNamePtr(xmlShmCb, xmlShmCb->objectNode, i);
		if (*name == NULL)
			continue;
		name++;
		count++;
	}
	
	xmlShmCb->meta_count = count;
	return value;
}

/*
	Description: 
		This function is used to free memory allocate at cmsXml_GetParameter()
	Parameters:
		pValue: return pointer of cmsXml_GetParameter()
		count: parameter count
	return:
		return CMS_OK
	must call this function everytime after cmsXml_getParameter()
		
*/
int cmsXml_freeParameterBuffer(parameterValue_t *pValue, int count)
{
	CMS_LOG(LL_FLOOD, "buf count is %d\n", count);
	free(pValue);
	return CMS_OK;
}


/*
	Description: 
		This function is used to free memory allocate at cmsXml_getParameterNameByID()
	Parameters:
		name: return double pointer of cmsXml_getParameterNameByID()
	return:
		return CMS_OK
	must call this function everytime after cmsXml_getParameterNameByID()
		
*/
int cmsXml_freeParameterNameBuffer(void **name)
{
	if((name != NULL) && ((*name) != NULL)){
		free(name);
		name = NULL;
	}
	
	return CMS_OK;
}

#if 0
int cmsSetL2Mode5Tuple(uint32_t en)
{
	cmsXmlCb_t *xmlShmCb= NULL;
	char objPathName[256] = {0};
	void *object = NULL;
	cmsoffset_t objOff=0;
	int usednum = 0;
	cmsObj_InternetGatewayDevice_X_GC_EXT_X_GC_L2_Mode_t *cms_X_GC_L2_Mode_Info = NULL;

	CMS_LOG(LL_INFO, "[%s-%d]--enter-- \n", __FUNCTION__, __LINE__);
	
	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL){
		return -1;
	}

	XML_LOCK(&xmlShmCb->cmsMutex->lock);
	sprintf(objPathName,"InternetGatewayDevice.X_GC_EXT.X_GC_L2_Mode");
	if((object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED)) == NULL){
		CMS_LOG(LL_ERROR, "fail to get InternetGatewayDevice.X_GC_EXT.X_GC_L2_Mode\r\n");
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		XMLSHMDEINIT(xmlShmCb);
		return -1;
	}
	cms_X_GC_L2_Mode_Info = (cmsObj_InternetGatewayDevice_X_GC_EXT_X_GC_L2_Mode_t *)object;
	usednum = cms_X_GC_L2_Mode_Info->ModuleUsed;
	

	//cmsXml_setOneParameterByPath(xmlShmCb, )

	if ( en == 0 )
	{
		if ( usednum > 0 )
			usednum--;
	}
	else
		usednum++;

	objOff = cmsXmlGetPtrOffset(xmlShmCb, object);

	paraValueSettingList_t *paralist = newParameterList();
	setParameterToList(paralist, "ModuleUsed", PARAMETER_TYPE_UINT8, &usednum);
	//cmsXmlSetParameterByParaList(xmlShmCb,objOff,paralist);
	freeParameterList(paralist);


	CMS_LOG(LL_INFO, "[%s-%d]--ModuleUsed=%d-- \n", __FUNCTION__, __LINE__,usednum);
	
	if ( usednum == 0 )
		cms_do_cmd("echo 0 > /proc/gcnat/l2_mode");
	else
		cms_do_cmd("echo 1 > /proc/gcnat/l2_mode");
	
	cms_do_cmd("echo 0 > /proc/gcnat/enable");
	cms_do_cmd("echo 1 > /proc/gcnat/enable");
	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);

	XMLSHMDEINIT(xmlShmCb);
	
	return 0;

}
#endif

